package com.zmovie.admin.controller.movie;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmovie.admin.constant.Constants;
import com.zmovie.admin.controller.vo.MovieVO;
import com.zmovie.common.error.BusinessException;
import com.zmovie.common.error.EnumBusinessError;
import com.zmovie.common.response.CommonReturnType;
import com.zmovie.common.utils.FileUtils;
import com.zmovie.framework.domain.*;
import com.zmovie.framework.domain.dto.ActorGroupDTO;
import com.zmovie.framework.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 挚爱之夕
 * @version 1.0
 * @implSpec 电影信息模块
 * @since 2023-11-30 12:19
 */
@Controller
@RequestMapping("/movie/info")
@Api(tags = "电影信息模块")
public class MovieInfoController {
    @Autowired
    private MovieService movieService;
    @Autowired
    private MovieAreaService movieAreaService;
    @Autowired
    private MovieAgeService movieAgeService;
    @Autowired
    private MovieToTypeService movieToTypeService;
    @Autowired
    private ActorMovieService actorMovieService;
    @Autowired
    private ActorRoleService actorRoleService;

    @GetMapping
    @ApiOperation("电影信息页面")
    public String index(Model model) {
        //查区域
        List<MovieArea> movieAreas = movieAreaService.listMovieArea(new MovieArea());
        model.addAttribute(Constants.MOVIE_AREAS_KEY, movieAreas);
        //查年代
        List<MovieAge> movieAges = movieAgeService.listMovieAge(new MovieAge());
        model.addAttribute(Constants.MOVIE_AGES_KEY, movieAges);
        //查电影分页
        Page<Movie> moviePage = movieService.pageMovie(new Movie(), Integer.valueOf(Constants.PAGE_NO), Integer.valueOf(Constants.PAGE_SIZE));
        model.addAttribute(Constants.MOVIE_PAGE_KEY, convert(moviePage));
        return "movie/movie_info";
    }

    @GetMapping("/{id}")
    @ResponseBody
    @ApiOperation("根据获取电影信息")
    public Object getMovie(@NotNull @PathVariable("id") Integer id) {
        return CommonReturnType.success(movieService.getById(id));
    }

    @PostMapping
    @ResponseBody
    @Transactional
    @ApiOperation("添加电影信息")
    public Object addMovie(@Validated Movie movie,
                           List<MultipartFile> posters,
                           List<MultipartFile> pictureFiles) throws BusinessException {
        try {
            //保存电影封面
            List<String> fileNameList = FileUtils.saveFile(posters, FileUtils.moviePath);
            String fileNameListJson = JSON.toJSONString(fileNameList);//序列化
            movie.setPoster(fileNameListJson); //图片路径集
            //保存电影图集
            fileNameList = FileUtils.saveFile(pictureFiles, FileUtils.moviePath);
            fileNameListJson = JSON.toJSONString(fileNameList);//序列化
            movie.setPictures(fileNameListJson);
            //保存到数据库
            movieService.save(movie);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(EnumBusinessError.OPERATOR_ERROR);
        }
        return CommonReturnType.success("添加成功!");
    }

    @PutMapping
    @ResponseBody
    @ApiOperation("修改电影信息")
    public Object updateMovie(@Validated Movie movie,
                              List<MultipartFile> posters,
                              List<MultipartFile> pictures) throws BusinessException {
        //参数校验
        if (movie.getId() == null) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        //先删除保存的图片
        deleteMovieFile(movie.getId());

        //保存电影封面
        List<String> fileNameList = FileUtils.saveFile(posters, FileUtils.moviePath);
        String fileNameListJson = JSON.toJSONString(fileNameList);//序列化
        movie.setPoster(fileNameListJson); //图片路径集
        //保存电影图集
        fileNameList = FileUtils.saveFile(pictures, FileUtils.moviePath);
        fileNameListJson = JSON.toJSONString(fileNameList);//序列化
        movie.setPictures(fileNameListJson);
        movieService.updateById(movie);
        return CommonReturnType.success("修改成功!");
    }

    @DeleteMapping("/{id}")
    @ResponseBody
    @ApiOperation("删除电影信息")
    public Object deleteMovie(@NotNull @PathVariable("id") Integer id) {
        //删除图片
        deleteMovieFile(id);
        movieService.removeById(id);
        return CommonReturnType.success("删除成功!");
    }

    @DeleteMapping
    @ResponseBody
    @ApiOperation("批量删除电影信息")
    public Object deleteMovieBatch(Integer[] id) throws BusinessException {
        //参数校验
        if (id == null || id.length == 0) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        //删除图片
        for(Integer i : id){
            deleteMovieFile(i);
        }
        movieService.removeByIds(Arrays.asList(id));
        return CommonReturnType.success("删除成功!");
    }

    @PostMapping("/search")
    @ApiOperation("搜索")
    public String search(Movie movie, Integer pageNo, Integer pageSize, Model model) {
        Page<Movie> moviePage = movieService.pageMovie(movie, pageNo, pageSize);
        model.addAttribute(Constants.MOVIE_PAGE_KEY, convert(moviePage));
        return "movie/movie_info :: movieList";
    }

    @PostMapping("/manage")
    @ApiOperation("加载电影类型和人员管理数据")
    public String manage(@NotNull Integer movieId, Model model){
        model.addAttribute("movieId", movieId);
        /*电影类型*/
        //查已关联电影类型(用于显示已绑定类型)
        List<MovieType> modalSelectedTypes = movieToTypeService.listRelatedMovieTypeByMovieId(movieId);
        model.addAttribute(Constants.MODAL_SELECTED_TYPES_KEY, modalSelectedTypes);
        //查未关联电影类型(用于下拉框选择)
        List<MovieType> modalSelectTypes = movieToTypeService.listNotRelatedMovieTypeByMovieId(movieId);
        model.addAttribute(Constants.MODAL_SELECT_TYPES_KEY, modalSelectTypes);
        /*人员管理*/
        //查演员角色
        List<ActorRole> modalSelectRoles = actorRoleService.listActorRole(new ActorRole());
        model.addAttribute(Constants.MODAL_SELECT_ROLES_KEY, modalSelectRoles);
        //查已关联演员(根据角色类型分组)
        List<ActorGroupDTO> modalSelectedActors = actorMovieService.listActorByMovieIdGroupByRole(movieId);
        model.addAttribute(Constants.MODAL_SELECTED_ACTORS_KEY, modalSelectedActors);
        //查未关联演员(用于下拉框选择)
        List<Actor> modalSelectActors = actorMovieService.listNotRelatedActorByMovieId(movieId);
        model.addAttribute(Constants.MODAL_SELECT_ACTORS_KEY, modalSelectActors);
        return "movie/movie_info :: modalData";
    }

    //删除保存的图片
    private void deleteMovieFile(Integer movieId){
        try {
            //封面
            String pictureJson = movieService.getById(movieId).getPoster();
            //反序列化
            List<String> fileNameList = JSON.parseArray(pictureJson, String.class);
            FileUtils.delete(fileNameList);
            //图片集
            pictureJson = (String)movieService.getById(movieId).getPictures();
            //反序列化
            fileNameList = JSON.parseArray(pictureJson, String.class);
            FileUtils.delete(fileNameList);
        } catch (BusinessException e) {
            e.printStackTrace();
        }
    }

    private Page<MovieVO> convert(Page<Movie> moviePage) {
        Page<MovieVO> movieVOPage = new Page<>();
        //复制
        BeanUtils.copyProperties(moviePage, movieVOPage);
        //转VO
        List<MovieVO> movieVOList = moviePage.getRecords().stream().map(this::convert).collect(Collectors.toList());
        movieVOPage.setRecords(movieVOList);
        return movieVOPage;
    }

    private MovieVO convert(Movie movie) {
        MovieVO movieVO = new MovieVO();
        //复制
        BeanUtils.copyProperties(movie, movieVO);
        //区域
        MovieArea area = movieAreaService.getById(movie.getAreaId());
        movieVO.setMovieArea(area);
        //年代
        MovieAge age = movieAgeService.getById(movie.getAgeId());
        movieVO.setMovieAge(age);
        //类型
        return movieVO;
    }
}
